/*************************************************
 Copyright © DusunIoT 2005-2023. All rights reserved.
 File name: common_dbg_log.h
 Author: yaoyuxi
 Version: V1.0
 Date: Tuesday, July 11, 2023 
 Description: 调试打印日志统一接口
 Others: none
 History: Created July 11, 2023  by:yaoyuxi
*************************************************/

#ifndef __DBG_LOG_H__
#define __DBG_LOG_H__

#include <stdio.h>
#include <stdint.h>
#include <stdarg.h>
#include <libgen.h> 
#include "common_types.h"
     
#ifdef __cplusplus
    extern "C" {
#endif


#ifdef WITH_LOG4C
#include "log4c.h"
#include "log4c/appender_type_rollingfile.h"
#include "log4c/rollingpolicy.h"
#include "log4c/rollingpolicy_type_sizewin.h"
#else 
#include <sys/time.h>
#endif


#ifdef WITH_LOG4C

#define DBG_PRIT       LOG4C_PRIORITY_DEBUG
#define DBG_INFO       LOG4C_PRIORITY_INFO 
#define DBG_WARN       LOG4C_PRIORITY_WARN  
#define DBG_ERR        LOG4C_PRIORITY_ERROR
#define DBG_CRIT       LOG4C_PRIORITY_CRIT
#define DBG_NONE       LOG4C_PRIORITY_NOTSET

#define HSLOG_CATEGORY_NAME "hs.log"
#define HSNVLOG_CATEGORY_NAME "hs_nv.log"
#define NV_PATH         "/etc/config/dusun/"
#else
/*
 * 串口日志等级类型宏定义
 */
#define DBG_PRIT          0x5       /*调试日志类型，默认情况下为关闭，只有调试时通过串口命令打开才会输出*/
#define DBG_INFO          0x4       /*运行中关键信息日志类型，默认情况下为关闭，只有调试时通过串口命令打开才会输出*/
#define DBG_WARN          0x3       /*运行中告警日志类型，默认情况下为开启，可能存在运行错误的地方输出的信息*/
#define DBG_ERR           0x2       /*运行中错误日志类型，默认情况下为开启，存在运行错误的地方输出的信息*/
#define DBG_CRIT          0x1       /*运行中接口交互数据日志类型，默认情况下为开启，系统运行各个模块之间交互数据信息输出*/
#define DBG_NONE          0x0       /*不打印任何日志信息*/
#endif 

/*
 * 默认模块ID宏定义
 */
#define DBG_LOG_DEFAULT_MODULE_ID         0xFFFFFFFF

/*
 * hostApp中alarm模块ID宏定义
 */
#define DBG_LOG_ALARM_GROUP_ID           0x00000001
#define DBG_LOG_ALARM_SAFETY_ID          0x00000002
#define DBG_LOG_ALARM_SCENARIO_ID        0x00000003

/*
 * hostApp中cloud模块ID宏定义
 */
#define DBG_LOG_CLOUD_MQTT_ID            0x00000001
#define DBG_LOG_CLOUD_RBAPI_ID           0x00000002

/*
 * hostApp中devStatus模块ID宏定义
 */
#define DBG_LOG_STATUS_BATTERY_ID        0x00000001
#define DBG_LOG_STATUS_STATION_ID        0x00000002
#define DBG_LOG_STATUS_SUBDEB_ID         0x00000004

/*
 * hostApp中event模块ID宏定义
 */
#define DBG_LOG_EVENT_GSM_ID             0x00000001
#define DBG_LOG_EVENT_SMS_ID             0x00000002

/*
 * hostApp中msgServer模块ID宏定义
 */
#define DBG_LOG_MSG_SERVER_ID            0x00000001

/*
 * hostApp中network模块ID宏定义
 */
#define DBG_LOG_NET_BASE_ID              0x00000001
#define DBG_LOG_NET_SSH_ID               0x00000002

/*
 * hostApp中system模块ID宏定义
 */
#define DBG_LOG_SYSTEM_ABILITY_ID        0x00000001
#define DBG_LOG_SYSTEM_CFG_ID            0x00000002
#define DBG_LOG_SYSTEM_DIAG_ID           0x00000004
#define DBG_LOG_SYSTEM_LOG_ID            0x00000008
#define DBG_LOG_SYSTEM_PARAM_ID          0x00000010
#define DBG_LOG_SYSTEM_SERIAL_ID         0x00000020
#define DBG_LOG_SYSTEM_INFO_ID           0x00000040
#define DBG_LOG_SYSTEM_TIME_ID           0x00000080
#define DBG_LOG_SYSTEM_UPG_ID            0x00000100
#define DBG_LOG_SYSTEM_WDOG_ID           0x00000200
#define DBG_LOG_SYSTEM_USER_ID           0x00000400
#define DBG_LOG_SYSTEM_STATUS_ID         0x00000800

/*
 * hostApp中UI模块ID宏定义
 */
#define DBG_LOG_UI_BUTTON_ID             0x00000001
#define DBG_LOG_UI_LED_ID                0x00000002

/*
 * common中模块ID宏定义
 */
#define DBG_LOG_COMMON_MEM_ID            0x00000001
#define DBG_LOG_COMMON_THREAD_ID         0x00000002

/*
 * localSubDevApp中模块ID宏定义
 */
#define DBG_LOG_LOCAL_KEYFOB_ID          0x00000001
#define DBG_LOG_LOCAL_KEYPAD_ID          0x00000002
#define DBG_LOG_LOCALDEV_ZIGBEE_ID       0x00000004
#define DBG_LOG_PROTOCAL_ZIGBEE_ID       0x00000008
#define DBG_LOG_LOCALDEV_RBF_ID          0x00000010
#define DBG_LOG_PROTOCAL_RBF_ID          0x00000020

/*
 * mobileApp中模块ID宏定义
 */
#define DBG_LOG_MOBILE_DIAL_ID           0x00000001
#define DBG_LOG_MOBILE_MSG_ID            0x00000002

/*
 * WifiSpeaker中模块ID宏定义
 */
#define DBG_LOG_WIFI_SPEAKER_ID           0x00000001
#define DBG_LOG_WIFI_SPEAKER_MSG_ID       0x00000002


/**
 * ATS中子模块功能ID宏定义
*/
#define DBG_LOG_ATS_NORMAL_ID             0x00000001


/*
 * 模块掩码宏定义
 */
#define DBG_LOG_DEFAULT_MODULE_MASK       0xFFFFFFFF
#define DBG_LOG_HOST_APP_ALARM_MASK       0x00010000
#define DBG_LOG_HOST_APP_CLOUD_MASK       0x00020000
#define DBG_LOG_HOST_APP_EVENT_MASK       0x00040000
#define DBG_LOG_HOST_APP_STATUS_MASK      0x00080000
#define DBG_LOG_HOST_APP_MSG_MASK         0x00100000
#define DBG_LOG_HOST_APP_NET_MASK         0x00200000
#define DBG_LOG_HOST_APP_SYSTEM_MASK      0x00400000
#define DBG_LOG_HOST_APP_UI_MASK          0x00800000
#define DBG_LOG_COMMON_MASK               0x01000000
#define DBG_LOG_LOCAL_DEV_APP_MASK        0x02000000
#define DBG_LOG_MOBILE_APP_MASK           0x02000000
#define DBG_LOG_WIFI_SPEAKER_MASK         0x04000000
#define DBG_LOG_ATS_MASK                  0x08000000


#define DBG_FILE          __FILE__       /*文件信息*/
#define DBG_LINE          __LINE__       /*行号*/
#define DBG_FUNC          __func__       /*函数名*/

/*
 * 终端显示颜色宏定义
 */
#define DBG_LOG_DEFAULT         39
#define DBG_LOG_RED             31
#define DBG_LOG_GREEN           32
#define DBG_LOG_YELLOW          33
#define DBG_LOG_BLUE            34
#define DBG_LOG_MAGENTA         35
#define DBG_LOG_CYAN            36
#define DBG_LOG_LIGHTGRAY       37
#define DBG_LOG_DARKGRAY        90
#define DBG_LOG_LIGHTRED        91
#define DBG_LOG_LIGHTGREEN      92
#define DBG_LOG_LIGHTYELLOW     93
#define DBG_LOG_LIGHTBLUE       94
#define DBG_LOG_LIGHTMAGENTA    95
#define DBG_LOG_LIGHTCYAN       96
#define DBG_LOG_WHIT            97

/*
 * 生成终端显示的颜色和格式定义宏
 */
#ifndef LOG_FMT_DISABLE
#define DBG_LOG_FMT_ESC(code)   "\e[" #code "m"
#else
#define DBG_LOG_FMT_ESC(code)
#endif
#define DBG_LOG_FMT(code)       DBG_LOG_FMT_ESC(code)
#define DBG_LOG_FMT_BOLD(code)  DBG_LOG_FMT_ESC(1) DBG_LOG_FMT_ESC(code)
#define DBG_LOG_FMT_CLEAR       DBG_LOG_FMT_ESC(0)

#define LOG_MAX_FMT_STR_SIZE        (4096)

RB_BOOL dbg_log_is_open(RB_UINT32 uiLevel, RB_UINT32 uiModuleId, RB_UINT32 uiModuleMask);
RB_VOID dbg_log_base_output(RB_INT8 *pDbgFile, const RB_INT32 pDbgLine, const RB_INT8 *pDbgFunc, const RB_UINT32 uiLevel, const RB_INT8 *pFmt, ...);

/*
 * 按模块和日志等级进行控制是否输入对应日志统一接口定义，供各个业务模块使用
 */
#define DBG_LOG(uiLevel, uiModuleId, uiModuleMask, ...)   do { \
        if (RB_TRUE == dbg_log_is_open(uiLevel, uiModuleId, uiModuleMask)) \
        { \
            dbg_log_base_output(basename(DBG_FILE), DBG_LINE, DBG_FUNC, uiLevel, __VA_ARGS__); \
        } \
    } while(0)
                           
/**@brief     获取日志时间戳字符串
* @param[in]  无
* @param[out] 无
* @return    日志字符串地址指针
*/
RB_INT8 *dbg_log_get_time_str();


#ifdef WITH_LOG4C

static LOG4C_INLINE void hslog_msg(const char *catName,int a_priority, const char* a_format,...)
{
    const log4c_category_t* a_category = log4c_category_get(catName);

    if (log4c_category_is_priority_enabled(a_category, a_priority)) {
        va_list va;
        va_start(va, a_format);
        log4c_category_vlog(a_category, a_priority, a_format, va);
        va_end(va);
    }                                
}

/* jio@2023-11-20 21:08 原因：加入非易失回滚日志接口 */
#define NV_LOG_INFO(...)    hslog_msg(HSNVLOG_CATEGORY_NAME, DBG_INFO,__VA_ARGS__)
#define NV_LOG_PRIT(...)    hslog_msg(HSNVLOG_CATEGORY_NAME, DBG_PRIT,__VA_ARGS__)
#define NV_LOG_ERR(...)     hslog_msg(HSNVLOG_CATEGORY_NAME, DBG_ERR,__VA_ARGS__)
#define NV_LOG_WARN(...)    hslog_msg(HSNVLOG_CATEGORY_NAME, DBG_WARN,__VA_ARGS__)


#define LOG_NV_INFO(...)   do          \
                            {           \
                                (printf(DBG_LOG_FMT_BOLD(DBG_LOG_GREEN)  "[%s][INF]" DBG_LOG_FMT_CLEAR "%s::%15s() " , dbg_log_get_time_str(), basename(DBG_FILE), DBG_FUNC), printf(__VA_ARGS__), printf("\n")); \
                                hslog_msg(HSLOG_CATEGORY_NAME, DBG_INFO,__VA_ARGS__); \
                                hslog_msg(HSNVLOG_CATEGORY_NAME, DBG_INFO,__VA_ARGS__); \
                            } while (0)

#define LOG_NV_ERR(...)   do          \
                            {           \
                                (printf(DBG_LOG_FMT_BOLD(DBG_LOG_RED)    "[%s][ERR]" DBG_LOG_FMT_CLEAR "%s::%15s() " , dbg_log_get_time_str(), basename(DBG_FILE), DBG_FUNC), printf(__VA_ARGS__), printf("\n")); \
                                hslog_msg(HSLOG_CATEGORY_NAME, DBG_ERR,__VA_ARGS__); \
                                hslog_msg(HSNVLOG_CATEGORY_NAME, DBG_ERR,__VA_ARGS__); \
                            } while (0)

#define DBG_LOG_INFO(...)   do          \
                            {           \
                                (printf(DBG_LOG_FMT_BOLD(DBG_LOG_GREEN)  "[%s][INF]" DBG_LOG_FMT_CLEAR "%s::%15s() " , dbg_log_get_time_str(), basename((char*)DBG_FILE), DBG_FUNC), printf(__VA_ARGS__), printf("\n")); \
                                hslog_msg(HSLOG_CATEGORY_NAME, DBG_INFO,__VA_ARGS__); \
                            } while (0)

#define DBG_LOG_PRIT(...)    do         \
                            {           \
                                (printf(DBG_LOG_FMT_BOLD(DBG_LOG_BLUE)   "[%s][DBG]" DBG_LOG_FMT_CLEAR "%s::%15s() " , dbg_log_get_time_str(), basename((char*)DBG_FILE), DBG_FUNC), printf(__VA_ARGS__), printf("\n")); \
                                hslog_msg(HSLOG_CATEGORY_NAME, DBG_PRIT,__VA_ARGS__); \
                            } while (0)
                            
                            
                           
#define DBG_LOG_ERR(...)    do          \
                            {           \
                                (printf(DBG_LOG_FMT_BOLD(DBG_LOG_RED)    "[%s][ERR]" DBG_LOG_FMT_CLEAR "%s::%15s() " , dbg_log_get_time_str(), basename((char*)DBG_FILE), DBG_FUNC), printf(__VA_ARGS__), printf("\n")); \
                                hslog_msg(HSLOG_CATEGORY_NAME, DBG_ERR,__VA_ARGS__); \
                            } while (0)

#define DBG_LOG_WARN(...)   do          \
                            {           \
                                (printf(DBG_LOG_FMT_BOLD(DBG_LOG_YELLOW) "[%s][WRN]" DBG_LOG_FMT_CLEAR "%s::%15s() " , dbg_log_get_time_str(), basename((char*)DBG_FILE), DBG_FUNC), printf(__VA_ARGS__), printf("\n")); \
                                hslog_msg(HSLOG_CATEGORY_NAME, DBG_WARN,__VA_ARGS__); \
                            } while (0)

static LOG4C_INLINE int hslog_init()
{
    log4c_init();

    log4c_category_t* hs_nv = log4c_category_get(HSNVLOG_CATEGORY_NAME);
    log4c_category_set_priority(hs_nv, LOG4C_PRIORITY_TRACE);

    log4c_appender_t* file_appender = log4c_appender_get("nvrollingfileappender");
    log4c_appender_set_type(file_appender, log4c_appender_type_get("rollingfile"));

    rollingfile_udata_t *rfup = rollingfile_make_udata();              
    rollingfile_udata_set_logdir(rfup, NV_PATH);
    rollingfile_udata_set_files_prefix(rfup, "nv");

    log4c_rollingpolicy_t *policyp = log4c_rollingpolicy_get("nvrollingpolicy");
    log4c_rollingpolicy_set_type(policyp, log4c_rollingpolicy_type_get("sizewin"));

    rollingpolicy_sizewin_udata_t *sizewin_udatap = sizewin_make_udata();
    sizewin_udata_set_file_maxsize(sizewin_udatap, 204800);
    sizewin_udata_set_max_num_files(sizewin_udatap, 5);
    log4c_rollingpolicy_set_udata(policyp,sizewin_udatap);

    rollingfile_udata_set_policy(rfup, policyp);
    log4c_appender_set_udata(file_appender, rfup);

    log4c_rollingpolicy_init(policyp, rfup);
    log4c_appender_set_layout(file_appender, log4c_layout_get("dated_local") );
    log4c_category_set_appender(hs_nv, file_appender);

	return 0;
}

static LOG4C_INLINE int hslog_fini()
{
	return(log4c_fini());
}

#else

#define NV_LOG_INFO(...)    
#define NV_LOG_PRIT(...)    
#define NV_LOG_ERR(...)    
#define NV_LOG_WARN(...)    
/*
 * 按不受模块和日志等级控制影响统一日志输入接口定义，供各个业务模块临时使用
 */
#define DBG_LOG_INFO(...)   (printf(DBG_LOG_FMT_BOLD(DBG_LOG_GREEN)  "[%s][INF]" DBG_LOG_FMT_CLEAR "%s::%15s() " , dbg_log_get_time_str(), DBG_FILE, DBG_FUNC), printf(__VA_ARGS__), printf("\n"))
#define DBG_LOG_PRIT(...)  (printf(DBG_LOG_FMT_BOLD(DBG_LOG_BLUE)   "[%s][DBG]" DBG_LOG_FMT_CLEAR "%s::%15s() " , dbg_log_get_time_str(), DBG_FILE, DBG_FUNC), printf(__VA_ARGS__), printf("\n"))
#define DBG_LOG_ERR(...)    (printf(DBG_LOG_FMT_BOLD(DBG_LOG_RED)    "[%s][ERR]" DBG_LOG_FMT_CLEAR "%s::%15s() " , dbg_log_get_time_str(), DBG_FILE, DBG_FUNC), printf(__VA_ARGS__), printf("\n"))
#define DBG_LOG_WARN(...)   (printf(DBG_LOG_FMT_BOLD(DBG_LOG_YELLOW) "[%s][WRN]" DBG_LOG_FMT_CLEAR "%s::%15s() " , dbg_log_get_time_str(), DBG_FILE, DBG_FUNC), printf(__VA_ARGS__), printf("\n"))

static inline int hslog_init()
{
	return 0;
}

static inline int hslog_fini()
{
	return 0;
}

#endif
/**@brief     打开某个或某几个模块的某个等级的串口打印信息
* @param[in]  uiModuleId:日志模块ID
* @param[in]  uiModuleMask:日志模块掩码
* @param[out] 无
* @return     无
*/
RB_VOID dbg_log_set_open(RB_UINT32 uiLevel, RB_UINT32 uiModuleId, RB_UINT32 uiModuleMask);

/**@brief     关闭某个或某几个模块的串口打印信息
* @param[in]  uiModuleId:日志模块ID
* @param[in]  uiModuleMask:日志模块掩码
* @param[out] 无
* @return     无
*/
RB_VOID dbg_log_set_close(RB_UINT32 uiModuleId, RB_UINT32 uiModuleMask);

RB_UINT32 dbg_log_get_current_mask();

RB_UINT32 dbg_log_get_current_level();
/**
 * @brief 获取全局日志相应功能mask输出模块设置
 * 
 * @return RB_UINT32 
 */
RB_UINT32 dbg_log_get_module(RB_UINT32 mask);


#ifdef __cplusplus
}
#endif

#endif  //__DBG_LOG_H__

